package com.cqndt.disaster.device.common.util;

import java.math.BigDecimal;
import org.springframework.util.StringUtils;
import com.cqndt.disaster.device.common.enums.CommandEnum;
import com.cqndt.disaster.device.common.enums.ConstantEnum;
import com.cqndt.disaster.device.common.enums.ConstantErrorEnum;
import com.cqndt.disaster.device.common.exception.ContrlException;
import static com.cqndt.disaster.device.common.util.CRC8.FindCRC;
import static com.cqndt.disaster.device.common.util.NumberChangeUtil.*;


/**
 * @author lhl
 * @Description 设备命令控制工具类 地表裂缝监测仪 墙裂缝监测仪 地面倾斜监测仪 降雨量 泥位 智能报警器
 * @Date 2019/1/5 12:50
 */
public class ContrlUtil {
    /**
     * 设置角度阈值
     *
     * @param deviceNo 设备编号
     * @param angle    角度 °
     * @param flag   1 地表裂缝监测仪 2 地面倾斜监测仪
     * @return
     */
    public static String setAngleThreshold(String deviceNo, BigDecimal angle, Integer flag) {

        //参数校验
        if (StringUtils.isEmpty(deviceNo) || StringUtils.isEmpty(angle)) {
            throw new ContrlException(ConstantErrorEnum.NOT_PARAM);
        }
        //设置参数
        StringBuilder builder = new StringBuilder();
        if (1==flag){
            builder.append(CommandEnum.SET_UP_ANGLE_AB04.getCode());//命令
        }else {
            builder.append(CommandEnum.SET_UP_ANGLE_AC04.getCode());//命令
        }

        String data = "02" + decimalToFloat(angle);
        builder.append(padLeft(Integer.toHexString(data.length() / 2), 2));//数据长度
        builder.append(data);//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2));//校验

        return newString(deviceNo, builder.toString()) + builder.toString();
    }


    /**
     * 设置拉线阈值
     *
     * @param deviceNo 设备编号
     * @param stayWire 拉线值 mm
     * @return
     */
    public static String setStayWire(String deviceNo, BigDecimal stayWire) {
        //参数校验
        if (StringUtils.isEmpty(deviceNo) || StringUtils.isEmpty(stayWire)) {
            throw new ContrlException(ConstantErrorEnum.NOT_PARAM);
        }
        //设置参数 4部分  头+长度+参数（命令和设置的参数）+校验码
        StringBuilder builder = new StringBuilder();
        builder.append(CommandEnum.SET_UP_STAYWIRE_AB06.getCode());//命令
        String data = "02" + decimalToFloat(stayWire);
        builder.append(padLeft(Integer.toHexString(data.length() / 2), 2));//长度
        builder.append(data);//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2));//校验

        return newString(deviceNo, builder.toString()) + builder.toString();
    }

    /**
     * 设置上传间隔
     *
     * @param deviceNo 设备编号
     * @param upLoad   值 min/次
     * @param flag   值 min/次
     * @return  1 地表裂缝监测仪 2 地面倾斜监测仪 3雨量计 4液位计
     */
    public static String setUpLoad(String deviceNo, BigDecimal upLoad,Integer flag) {
        //参数校验
        if (StringUtils.isEmpty(deviceNo) || StringUtils.isEmpty(upLoad)) {
            throw new ContrlException(ConstantErrorEnum.NOT_PARAM);
        }
        //设置参数
        StringBuilder builder = new StringBuilder();
        if (1==flag){
            builder.append(CommandEnum.SET_UP_UPLOAD_AB0D.getCode());//命令
        }else if (2==flag){
            builder.append(CommandEnum.SET_UP_UPLOAD_AC0D.getCode());//命令
        }else if(3==flag){
            builder.append(CommandEnum.SET_UP_UPLOAD_AE0D.getCode());//命令
        }else {
            builder.append(CommandEnum.SET_UP_MUD_AF0D.getCode());//命令
        }
        String data = "02" + upLoadCycle(upLoad);
        builder.append(padLeft(Integer.toHexString(data.length() / 2), 2));//长度
        builder.append(data);//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2)); //校验

        return newString(deviceNo, builder.toString()) + builder.toString();
    }

    /**
     * 雨量计
     *
     * @param deviceNo 设备编号
     * @param rain     雨量值
     * @return
     */
    public static String rainFall(String deviceNo, BigDecimal rain) {
        //参数校验
        if (StringUtils.isEmpty(deviceNo) || StringUtils.isEmpty(rain)) {
            throw new ContrlException(ConstantErrorEnum.NOT_PARAM);
        }
        //设置参数 4部分  头+长度+参数（命令和设置的参数）+校验码
        StringBuilder builder = new StringBuilder();
        builder.append(CommandEnum.SET_UP_RAINFALL_AE06.getCode());//命令
        String data = "02"+decimalToFloat(rain);
        builder.append(padLeft(Integer.toHexString(data.length() / 2), 2));//长度
        builder.append(data);//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2)); //校验

        return newString(deviceNo, builder.toString()) + builder.toString();
    }


    /**
     * 设置声光告警
     *
     * @param deviceNo   设备编号
     * @param soundLight 有效值范围0-7，=0表示不播放任何一条语音，=1-7表示播放对应的语音
     * @return
     */
    public static String setAlarm(String deviceNo, Integer soundLight) {
        //参数校验
        if (StringUtils.isEmpty(deviceNo) || StringUtils.isEmpty(soundLight)) {
            throw new ContrlException(ConstantErrorEnum.NOT_PARAM);
        }
        //设置参数 4部分  头+长度+参数（命令和设置的参数）+校验码
        StringBuilder builder = new StringBuilder();
        builder.append(CommandEnum.SET_UP_SHOUDLIGHT_AD04.getCode());//命令
        String data = setAlarms(soundLight);
        builder.append(padLeft(Integer.toHexString(data.length() / 2), 2));//长度
        builder.append(data);//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2)); //校验

        return newString(deviceNo, builder.toString()) + builder.toString();

    }

    /**
     * 设置采样间隔
     *
     * @param deviceNo 设备编号
     * @param sampling 分钟值
     * @param flag  1 地表裂缝监测仪 2 地面倾斜监测仪 3雨量计 4液位计
     * @return
     */
    public static String setsampling(String deviceNo, Integer sampling,Integer flag) {
        //参数校验
        if (StringUtils.isEmpty(deviceNo) || StringUtils.isEmpty(sampling)) {
            throw new ContrlException(ConstantErrorEnum.NOT_PARAM);
        }
        //设置参数
        StringBuilder builder = new StringBuilder();
        if(1==flag){
            builder.append(CommandEnum.SET_UP_SAMPLING_AB0F.getCode());
        }else if (2==flag){
            builder.append(CommandEnum.SET_UP_SAMPLING_AC0F.getCode());
        }else if (3==flag){
            builder.append(CommandEnum.SET_UP_SAMPLING_AE0F.getCode());
        }else {
            builder.append(CommandEnum.SET_UP_MUD_AF0F.getCode());
        }
        String data = "02" + setSamp(sampling);
        builder.append(padLeft(Integer.toHexString(data.length() / 2), 2));//长度
        builder.append(data);//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2)); //校验

        return newString(deviceNo, builder.toString()) + builder.toString();
    }

    /**
     * 获取版本
     * @param sn 设备编号
     * @param type 1-地表裂缝；2-墙裂缝；3-地面倾斜；4-降雨量；5-泥位；6-报警器
     */
    public static String getSoftVersion(String sn, Integer type) {
        //设置参数 4部分  头+长度+参数（命令和设置的参数）+校验码
        StringBuilder builder = new StringBuilder();
        switch (type){
            case 1:
            case 2:builder.append(CommandEnum.SET_UP_GETVERSION_AB0E.getCode());
                break;
            case 3:builder.append(CommandEnum.SET_UP_GETVERSION_AC0E.getCode());break;
            case 4:builder.append(CommandEnum.SET_UP_GETVERSION_AE0E.getCode());break;
            case 5:builder.append(CommandEnum.SET_UP_GETVERSION_AF0E.getCode());break;
            case 6:builder.append(CommandEnum.SET_UP_GETVERSION_AD0E.getCode());break;
            default:;
        }
        String data = "01000000";
        builder.append(padLeft(Integer.toHexString(data.length() / 2), 2));//长度
        builder.append(data);//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2)); //校验

        return newString(sn, builder.toString());
    }

    /**
     * 升级包命令
     *
     * @param deviceNo 设备编号
     * @param Indexes  索引标号
     * @param len      数据长度
     * @param data     数据包数据
     * @return
     */
    public static String upGrade(String deviceNo,Integer Indexes, Integer len, String data,String sn) {
        StringBuilder builder = new StringBuilder();
        StringBuilder builderData = new StringBuilder();
        switch (sn){
            case "0f03": builder.append("F3AB");break;//命令
            case "0f04": builder.append("F3AC");break;//命令
            case "1301": builder.append("F3AD");break;//命令
            case "1201": builder.append("F3AE");break;//命令
            case "1401": builder.append("F3AF");break;//命令
            default:
        }

        //第二部分：数据部分
        builderData.append("02");//标记
        builderData.append(sortHighShort(padLeft(Integer.toHexString(Indexes),8)));//升级包索引
        builderData.append(sortHighShort(padLeft(Integer.toHexString(len),8)));//当前下发升级包长度
        builderData.append(sortHighShort(padLeft(Long.toHexString(CRC8.crc32(NumberChangeUtil.stringToByte(data))),8)));//crc32
        builderData.append(data);//数据

        builder.append(padLeft(Integer.toHexString(builderData.toString().length() / 2), 2));//长度
        builder.append(builderData.toString());
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2));//crc8
        return newString(deviceNo, builder.toString()) + builder.toString();
    }

    /**
     * 服务器向设备发送最新软件版本
     *
     * @param deviceNo   设备的sn
     * @param version    最新软件版本
     * @param len        升级包总长度
     * @param pakeageNum 分包总个数
     * @param data       文件总的内容
     * @return
     */
    public static String sendNewVersion(String deviceNo, String version, Integer len, Integer pakeageNum, String data,String sn) {
        StringBuilder builderData = new StringBuilder();
        StringBuilder builder = new StringBuilder();

        switch (sn){
            case "0f03": builder.append("F1AB");break;//命令
            case "0f04": builder.append("F1AC");break;//命令
            case "1301": builder.append("F1AD");break;//命令
            case "1201": builder.append("F1AE");break;//命令
            case "1401": builder.append("F1AF");break;//命令
            default:
        }
        //第二部分：数据部分
        builderData.append("02");
        builderData.append(sortHighShort(version.replaceAll("\\.", "")));//最新软件版本（2B）
        builderData.append(sortHighShort(padLeft(Integer.toHexString(len),8)));//升级包总长度。（4B）
        builderData.append(sortHighShort(padLeft(Long.toHexString(CRC8.crc32(NumberChangeUtil.stringToByte(data))),8)));//crc校验（4B）
        builderData.append(sortHighShort(padLeft(Integer.toHexString(pakeageNum), 8)));//分包总个数（4B）

        builder.append(padLeft(Integer.toHexString(builderData.toString().length() / 2), 2));//长度
        builder.append(builderData.toString());//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2));//crc8
        return newString(deviceNo, builder.toString()) + builder.toString();
    }

    /**
     * 拼接新字符串
     *
     * @param oldString 旧串
     * @param deviceNo  设备编号
     * @return
     */
    private static String newString(String deviceNo, String oldString) {
        return ConstantEnum.DEVICE_TYPE_NEW.getType() +
                deviceNo;
    }

    /**
     * 液位阈值设置
     * @param sn 设备编号
     * @param mud 液位阈值
     * @return
     */
    public static String setMud(String sn, BigDecimal mud) {
        //设置参数 4部分  头+长度+参数（命令和设置的参数）+校验码
        StringBuilder builder = new StringBuilder();
        builder.append(CommandEnum.SET_UP_MUD_AF04.getCode());//命令
        String data = "02"+decimalToFloat(mud);
        builder.append(padLeft(Integer.toHexString(data.length() / 2), 2));//长度
        builder.append(data);//数据
        builder.append(padLeft(Integer.toHexString(FindCRC(stringToByte(builder.toString()))), 2)); //校验

        return newString(sn, builder.toString()) + builder.toString();
    }
}
